<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>WebPosterWall</title>
    <link rel="stylesheet" href="./css/style.css" />


    <!-- 引入本地的 Element Plus 样式表 -->
    <link rel="stylesheet" href="./css/element.css" />
    <!-- 引入 Vue 3 版本 -->
    <script src="./js/vue.global.js"></script>
    <!-- 引入 Element Plus 组件库 -->
    <script src="./js/element.js"></script>
    <!-- 引入 mitt -->
    <script src="./js/mitt.umd.js"></script>

    <script type="module" src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.esm.js"></script>
    <script nomodule src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.js"></script>

</head>

<body>
    <!-- 右上角的切换按钮 -->
    <div class="menuToggle"></div>
    <!-- 顶栏 -->
    <div class="top-nav">
        <a href="#">ASMR</a>
        <a href="#">Games</a>
        <a href="#">JAV</a>
        <div id="search-app">
            <!-- 排序 下拉菜单 -->
            <div class="dropdown-container">
                <label for="sort">排序方式：</label>
                <select id="sort" v-model="sortOption" class="sort-dropdown" @change="selectSortOption($event)">
                    <option value="newest">最新收录</option>
                    <option value="releaseDateDesc">发售日期倒序</option>
                    <option value="releaseDateAsc">发售日期顺序</option>
                    <option value="salesDesc">销量倒序</option>
                    <option value="salesAsc">销量顺序</option>
                    <option value="priceDesc">价格倒序</option>
                    <option value="priceAsc">价格顺序</option>
                    <option value="ratingDesc">评分倒序</option>
                    <option value="ratingAsc">评分顺序</option>
                    <option value="reviewsDesc">评价数量倒序</option>
                    <option value="reviewsAsc">评价数量顺序</option>
                    <option value="rjCodeDesc">RJ号倒序</option>
                    <option value="rjCodeAsc">RJ号顺序</option>
                </select>
            </div>
            <!-- 高级搜索按钮 -->
            <button type="button" class="advanced-search-btn" @click="toggleAdvancedSearch">
                高级搜索
            </button>
            <!-- 搜索框 -->
            <form class="search-form" @submit.prevent="handleSearch">
                <input type="text" placeholder="Search..." name="search" v-model="searchTerm" />
                <button type="submit">
                    <ion-icon name="search-outline"></ion-icon>
                </button>
            </form>

            <!-- 高级搜索弹窗 -->
            <div v-if="showAdvancedSearch" class="advanced-search-modal">
                <div class="modal-overlay" @click="toggleAdvancedSearch"></div>
                <div class="modal-content">
                    <span class="close" @click="toggleAdvancedSearch">&times;</span>
                    <h3>Advanced Search</h3>

                    <!-- Age and Type Section -->
                    <div class="filters-section">
                        <h4>Age</h4>
                        <div class="checkbox-group">
                            <label><input type="checkbox" v-model="selectedAges" value="18"> R18</label>
                            <label><input type="checkbox" v-model="selectedAges" value="15"> R15</label>
                            <label><input type="checkbox" v-model="selectedAges" value="0"> 全年龄</label>
                        </div>

                        <h4>Type</h4>
                        <div class="checkbox-group">
                            <label><input type="checkbox" v-model="selectedTypes" value="SOU"> 音声・ASMR</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="DNV"> 电子小说</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="ADV"> 冒险</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="PZL"> 益智</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="SLN"> 模拟</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="RPG"> 角色扮演</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="ACN"> 动作</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="ETC"> 其他游戏</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="MNG"> 漫画</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="MOV"> 视频</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="ICG"> CG・画</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="MUS"> 音乐</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="TOL"> 工具/装饰</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="AMT"> 声音素材</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="IMT"> 图片素材</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="QIZ"> 解谜</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="STG"> 射击</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="NRE"> 小说</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="ET3"> 其他</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="TBL"> 桌游</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="TYP"> 打字</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="VCM"> 音声漫画</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="SCM"> 剧画</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="WBT"> Webtoon</label>
                            <label><input type="checkbox" v-model="selectedTypes" value="KSV"> 官能小说</label>
                        </div>
                    </div>

                    <!-- Price Range Section -->
                    <div class="price-section">
                        <h4>Price Range</h4>
                        <div class="price-inputs">
                            <input type="number" placeholder="Min Price" v-model="minPrice" />
                            <span>to</span>
                            <input type="number" placeholder="Max Price" v-model="maxPrice" />
                            <button @click="addPriceRange">Add Price Range</button>
                        </div>
                        <ul>
                            <li v-for="(range, index) in priceRanges" :key="index">
                                {{ range.min }} to {{ range.max }} <span @click="removePriceRange(index)">×</span>
                            </li>
                        </ul>
                    </div>

                    <!-- Tags, VA, Circles Section -->
                    <div class="tags-section">
                        <h4>Tags</h4>
                        <input type="text" v-model="newTag" placeholder="Add a tag" @keyup.enter="addTag" />
                        <ul>
                            <li v-for="(tag, index) in tags" :key="index">
                                {{ tag }} <span @click="removeTag(index)">×</span>
                            </li>
                        </ul>

                        <h4>VA</h4>
                        <input type="text" v-model="newVA" placeholder="Add a VA" @keyup.enter="addVA" />
                        <ul>
                            <li v-for="(va, index) in vas" :key="index">
                                {{ va }} <span @click="removeVA(index)">×</span>
                            </li>
                        </ul>

                        <h4>Circles</h4>
                        <input type="text" v-model="newCircle" placeholder="Add a Circle" @keyup.enter="addCircle" />
                        <ul>
                            <li v-for="(circle, index) in circles" :key="index">
                                {{ circle }} <span @click="removeCircle(index)">×</span>
                            </li>
                        </ul>
                    </div>

                    <button class="apply-btn" @click="handleAdvancedSearch">Apply</button>
                </div>
            </div>
        </div>

    </div>

    <!-- 侧边栏 -->
    <div class="sidebar">
        <ul>
            <li class="logo" style="--bg: #333">
                <a href="#">
                    <div class="icon"><ion-icon name="logo-apple"></ion-icon></div>
                    <div class="text">Web Poster Wall</div>
                </a>
            </li>
            <div class="menu-list">
                <li style="--bg: #ffa117" class="active">
                    <a href="#" id="allPostersBtn">
                        <div class="icon"><ion-icon name="apps"></ion-icon></div>
                        <div class="text">All</div>
                    </a>
                </li>

                <li style="--bg: #ff6f91">
                    <a href="#" id="favoriteButton">
                        <div class="icon">
                            <ion-icon name="heart-outline"></ion-icon>
                        </div>
                        <div class="text">Favorite</div>
                    </a>
                </li>

                <li style="--bg: #0fc70f">
                    <a href="#" id="tagsButton">
                        <div class="icon">
                            <ion-icon name="bookmark-outline"></ion-icon>
                        </div>
                        <div class="text">tags</div>
                    </a>
                </li>

                <li style="--bg: #2196f3">
                    <a href="#" id="vaButton">
                        <div class="icon">
                            <ion-icon name="mic-outline"></ion-icon>
                        </div>
                        <div class="text">voice actor</div>
                    </a>
                </li>

                <li style="--bg: #b145e9">
                    <a href="#" id="circleButton">
                        <div class="icon"><ion-icon name="person-outline"></ion-icon></div>
                        <div class="text">circle</div>
                    </a>
                </li>

                <li style="--bg: #c0c0c0">
                    <a href="#" id="settingsButton">
                        <div class="icon">
                            <ion-icon name="settings-outline"></ion-icon>
                        </div>
                        <div class="text">Settings</div>
                    </a>
                </li>
            </div>
            <div class="bottom">
                <li style="--bg: #333">
                    <a href="#">
                        <div class="icon">
                            <div class="imgBx">
                                <img src="./images/user.jpg" alt="user" />
                            </div>
                        </div>
                        <div class="text">Kud</div>
                    </a>
                </li>

                <li style="--bg: #333">
                    <a href="#">
                        <div class="icon">
                            <ion-icon name="log-out-outline"></ion-icon>
                        </div>
                        <div class="text">Logout</div>
                    </a>
                </li>
            </div>
        </ul>
    </div>
    
    <!-- 海报墙部分 -->
    <div class="poster-wall">
        <!-- 海报内容 -->
        <div v-for="poster in posters" :key="poster.rjCode" class="poster-item">
            <!-- 封面图 -->
            <img :src="'../covers/' + poster.rjCode + '.jpg'" :alt="poster.rjCode" class="poster-image" />
            <!-- 产品信息 -->
            <div class="poster-info">
                <h2 class="poster-title" :title="poster.title">{{ poster.title }}</h2>
                
                <!-- 评分和标签组合 -->
                <div class="poster-meta">
                    <div class="rating-tags">
                        <div class="star_wrap">
                            <span class="rate" :data-rating="poster.rating"></span>
                        </div>
                        <div class="meta-tags">
                            <span class="meta-tag" v-if="poster.lang">{{poster.lang}}</span>
                            <span class="meta-tag sub" v-if="poster.isSub">字幕</span>
                            <span class="meta-tag vr" v-if="poster.isVR">VR</span>
                            <span class="meta-tag age" v-if="poster.ageCategory" 
                                  :class="getAgeClass(poster.ageCategory)">
                                {{poster.ageCategory}}
                            </span>
                        </div>
                    </div>
                </div>

                <!-- 社团和RJ号 -->
                <div class="poster-circle">
                    <span class="circle-name">{{poster.circle}}</span>
                    <span class="rj-code">{{poster.rjCode}}</span>
                </div>

                <!-- 声优列表 -->
                <div class="poster-va" v-if="poster.vas && poster.vas.length">
                    <div class="va-list">
                        <span class="va-item" v-for="va in poster.vas" :key="va">{{va}}</span>
                    </div>
                </div>

                <!-- 标签云 -->
                <div class="poster-tags" v-if="poster.tags && poster.tags.length">
                    <span class="tag" v-for="tag in poster.tags" :key="tag">{{tag}}</span>
                </div>
            </div>

        </div>

        <!-- 分页功能 -->
        <div class="pagination">
            <el-pagination v-model:current-page="current" v-model:page-size="pageSize" :page-sizes="[15, 30, 45, 60]"
                :size="size" :disabled="disabled" :background="background"
                layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handleSizeChange"
                @current-change="handleCurrentChange" />
        </div>

    </div>

    <div class="favorite-page" style="display: none;">

    </div>

    <!-- Tags页面 -->
    <div class="tags-page" style="display: none;">
        <!-- 搜索框 -->
        <div class="tags-container">
            <form class="search-bar" @submit.prevent="handleSearchTags">
                <input type="text" placeholder="Search for a tag..." name="search" v-model="searchTerm" />
                <!-- <button type="submit">
                    <ion-icon name="search-outline"></ion-icon>
                </button> -->
            </form>
        </div>

        <!-- 标签显示区域 -->
        <div class="tags-container">
            <button v-for="tag in tags" :key="tag.name" class="tag-button">
                {{ tag.name }} &nbsp; {{ tag.count }}
            </button>
        </div>
    </div>

    <div class="va-page" style="display: none;">
        <!-- 搜索框 -->
        <div class="tags-container">
            <form class="search-bar" @submit.prevent="handleSearchVA">
                <input type="text" placeholder="Search for a va..." name="search" v-model="searchTerm" />
            </form>
        </div>

        <!-- 标签显示区域 -->
        <div class="tags-container">
            <button v-for="va in vas" :key="va.name" class="tag-button">
                {{ va.name }} &nbsp; {{ va.count }}
            </button>
        </div>
    </div>

    <div class="circle-page" style="display: none;">
        <!-- 搜索框 -->
        <div class="tags-container">
            <form class="search-bar" @submit.prevent="handleSearchCircle">
                <input type="text" placeholder="Search for a circle..." name="search" v-model="searchTerm" />
            </form>
        </div>

        <!-- 标签显示��域 -->
        <div class="tags-container">
            <button v-for="circle in circles" :key="circle.name" class="tag-button">
                {{ circle.name }} &nbsp; {{ circle.count }}
            </button>
        </div>
    </div>

    <!-- 设置页面 -->
    <div class="settings-page" style="display: none;">

        <div class="settings-item">
            <h2>添加文件夹</h2>

            <label for="folderName">文件夹名称:</label>
            <input type="text" id="folderName" v-model="folderForm.folderName" required />

            <label for="folderPath">文件夹路径:</label>
            <input type="text" id="folderPath" v-model="folderForm.folderPath" required />

            <button class="settingItemBtn" @click="handleFolderAdd">添加</button>

        </div>

        <div class="settings-item">
            <h2>已添加文件夹</h2>
            <ul class="folder-list">
                <li v-for="(folder, index) in folders" :key="index" class="folder-item">
                    <label class="folder-name">{{ folder.folderName }}</label>
                    <div class="folder-details">
                        <input type="text" class="folder-path" :value="folder.folderPath" readonly />
                        <div class="folder-buttons">
                            <button @click="scanFolder(folder.folderPath)">扫描</button>
                            <button @click="removeFolder(index)">删除</button>
                        </div>
                    </div>
                </li>
            </ul>
        </div>

        <div class="settings-item">
            <h2>设置代理</h2>
            <label for="proxyIP">代理地址:</label>
            <input type="text" id="proxyIP" v-model="proxySettings.proxyIP" placeholder="proxySettings.proxyIP"
                required />

            <label for="proxyPort">端口号:</label>
            <input type="number" id="proxyPort" v-model="proxySettings.proxyPort" placeholder="proxySettings.proxyPort"
                required />

            <button class="settingItemBtn" @click="saveProxySettings">保存</button>

        </div>
    </div>

    <script src="./js/script.js"></script>

    <script>
        // 事件总线，用于实例间通信
        const eventBus = mitt();
        // 搜索框 Vue 实例
        const searchApp = {
            data() {
                return {
                    searchTerm: '',
                    sortOption: 'newest',
                    showAdvancedSearch: false,
                    selectedAges: [],
                    selectedTypes: [],
                    minPrice: '',
                    maxPrice: '',
                    priceRanges: [],
                    newTag: '',
                    tags: [],
                    newVA: '',
                    vas: [],
                    newCircle: '',
                    circles: []
                }
            },
            methods: {
                handleSearch() {
                    // 触发事件，将搜索词发送给海报墙实例
                    eventBus.emit('search', this.searchTerm);
                },
                selectSortOption(event) {
                    // 触发事件，将搜索词发送给海报墙实例
                    this.sortOption = event.target.value;
                    eventBus.emit('select', this.sortOption);
                },
                toggleAdvancedSearch() {
                    this.showAdvancedSearch = !this.showAdvancedSearch;
                },
                handleAdvancedSearch() {
                    console.log('Advanced Search Filters:', {
                        ages: this.selectedAges,
                        types: this.selectedTypes,
                        priceRanges: this.priceRanges,
                        tags: this.tags,
                        vas: this.vas,
                        circles: this.circles
                    });
                    this.toggleAdvancedSearch();
                },
                addPriceRange() {
                    if (this.minPrice && this.maxPrice) {
                        this.priceRanges.push({ min: this.minPrice, max: this.maxPrice });
                        this.minPrice = '';
                        this.maxPrice = '';
                    }
                },
                removePriceRange(index) {
                    this.priceRanges.splice(index, 1);
                },
                addTag() {
                    if (this.newTag) {
                        this.tags.push(this.newTag);
                        this.newTag = '';
                    }
                },
                removeTag(index) {
                    this.tags.splice(index, 1);
                },
                addVA() {
                    if (this.newVA) {
                        this.vas.push(this.newVA);
                        this.newVA = '';
                    }
                },
                removeVA(index) {
                    this.vas.splice(index, 1);
                },
                addCircle() {
                    if (this.newCircle) {
                        this.circles.push(this.newCircle);
                        this.newCircle = '';
                    }
                },
                removeCircle(index) {
                    this.circles.splice(index, 1);
                }
            }
        }

        // 创建并挂载 Vue 应用实例
        Vue.createApp(searchApp).mount('#search-app');

        const App = {
            data() {
                return {
                    posters: [], // 存储海报数据
                    searchQuery: '', // 当前的搜索查询词
                    current: 1, // 当前分页页码
                    total: 0, // 数据总数
                    pageSize: 15, // 每页显示条目个数
                    sortOption: 'newest' // 排序方��
                }
            },
            created() {
                // 组件创建时，调用 fetchPosters() 方法获取海报数据
                this.fetchPosters();
                // 监听搜索框发来的搜索事件
                eventBus.on('search', searchTerm => {
                    this.searchQuery = searchTerm;
                    this.current = 1; // 重置到第一页
                    this.fetchPosters(); // 重新获取数据
                });
            },
            computed: {
                sortedProducts() {
                    return this.products.sort((a, b) => {
                        if (this.sortKey === 'price') {
                            return a.price - b.price;
                        } else if (this.sortKey === 'title') {
                            return a.title.localeCompare(b.title);
                        }
                    });
                }
            },
            methods: {
                getAgeClass(ageCategory) {
                    switch(ageCategory) {
                        case 'R18': return 'r18';
                        case 'R-15': return 'r15';
                        case '全年龄': return 'all';
                        default: return '';
                    }
                },
                async fetchPosters() {
                    try {
                        const response = await fetch(`http://localhost:3000/api/products?search=${this.searchQuery}&current=${this.current}&pageSize=${this.pageSize}`);
                        const data = await response.json();
                        console.log(data);
                        this.posters = data.result; // 将数据存储到 posters 数组中
                        this.total = data.total; // 设置数据总数
                    } catch (error) {
                        console.error('Error fetching posters:', error);
                    }
                },
                // 处理每页显示条目个数切换
                handleSizeChange(val) {
                    this.pageSize = val;
                    this.fetchPosters();
                },
                // 处理分页切换
                handleCurrentChange(val) {
                    this.current = val;
                    this.fetchPosters();
                }
            }
        }

        // 创建并挂载 Vue 应用实例
        const app = Vue.createApp(App);
        app.use(ElementPlus);
        app.mount('.poster-wall');

        const App1 = {
            data() {
                return {
                    folderForm: { // 用户输入表单的初始值
                        folderName: '',
                        folderPath: ''
                    },
                    folders: [], // 存储已添加的文件夹
                    proxySettings: {
                        proxyIP: '',
                        proxyPort: ''
                    }
                }
            },
            created() {
                this.fetchConfig()
            },
            methods: {
                async fetchConfig() {
                    try {
                        const response = await fetch('http://localhost:3000/api/config/fetchConfig');
                        const config = await response.json();
                        // console.log(config);
                        this.folders = config.scanFolder; // 将数据存储到 folders 数组中
                        this.proxySettings.proxyIP = config.proxyIP;
                        this.proxySettings.proxyPort = config.proxyPort;
                    } catch (error) {
                        console.error('获取配置信息失败：', error);
                    }
                },
                async handleFolderAdd() {
                    if (this.folderForm.folderName && this.folderForm.folderPath) {
                        // 检查是否有相同��� name 或 path
                        const isDuplicate = this.folders.some(folder =>
                            folder.folderName === this.folderForm.folderName || folder.folderPath === this.folderForm.folderPath
                        );
                        if (isDuplicate) {
                            console.log('错误: 已有相同的别名或路径，不能添加重复项');
                        } else {
                            this.folders.push({ ...this.folderForm });
                            console.log('folders', this.folders);
                            try {
                                const response = await fetch('http://localhost:3000/api/config/addFolder', {
                                    method: 'POST',
                                    headers: {
                                        'Content-Type': 'application/json;charset=UTF-8'
                                    },
                                    body: JSON.stringify(this.folderForm)
                                })
                                // 清空表单
                                this.folderForm.folderName = '';
                                this.folderForm.folderPath = '';

                                const result = await response.json();
                                console.log(result); // 打印���功添加的文件夹信息
                            } catch (error) {
                                console.error('添加文件夹失败:', error);
                            }
                        }
                    }
                },
                async removeFolder(index) {
                    try {
                        const response = await fetch('http://localhost:3000/api/config/removeFolder', {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/json;charset=UTF-8'
                            },
                            body: JSON.stringify({ index: index })
                        })

                        const result = await response.json();
                        console.log(result);
                        this.folders.splice(index, 1);
                    } catch (error) {
                        console.error('移除文件夹失败：', error);
                    }
                },
                async scanFolder(path) {
                    console.log('正在扫描文件夹: ', path);
                    try {
                        const response = await fetch('http://localhost:3000/api/scan', {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/json;charset=UTF-8'
                            },
                            body: JSON.stringify({ scanPath: path })
                        })
                        const result = await response.json();
                        alert(result);
                    } catch (error) {
                        console.error('扫描失败：', error);
                    }
                },
                async saveProxySettings() {
                    try {
                        // console.log(this.proxySettings)
                        const response = await fetch('http://localhost:3000/api/config/setProxy', {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/json;charset=UTF-8'
                            },
                            body: JSON.stringify(this.proxySettings)
                        })
                        const result = await response.json();
                        console.log('返回信息：', result); // 打印成功添加的文件夹信息
                    } catch (error) {
                        console.error('设置代理失败：', error);
                    }
                }
            }
        }
        const app1 = Vue.createApp(App1);
        app1.mount('.settings-page');

        const App2 = {
            data() {
                return {
                    tags: [],
                    searchTerm: '' // 搜索框中的输入
                }
            },
            created() {
                this.fetchTags();
            },
            methods: {
                handleSearchTags() {
                    this.fetchTags();
                },
                async fetchTags() {
                    try {
                        const response = await fetch(`http://localhost:3000/api/tags?search=${this.searchTerm}`);
                        const result = await response.json();
                        console.log('Tags:', result);
                        this.tags = result;
                    } catch (error) {
                        console.error('获取Tags失败：', error);
                    }
                }
            }
        }
        const app2 = Vue.createApp(App2);
        app2.mount('.tags-page')

        const App3 = {
            data() {
                return {
                    vas: [],
                    searchTerm: '' // 搜索框中的输入
                }
            },
            created() {
                this.fetchVA();
            },
            methods: {
                handleSearchVA() {
                    this.fetchVA();
                },
                async fetchVA() {
                    try {
                        const response = await fetch(`http://localhost:3000/api/vas?search=${this.searchTerm}`);
                        const result = await response.json();
                        console.log('VA:', result);
                        this.vas = result;
                    } catch (error) {
                        console.error('获取vas失败：', error);
                    }
                }
            }
        }
        const app3 = Vue.createApp(App3);
        app3.mount('.va-page');

        const App4 = {
            data() {
                return {
                    circles: [],
                    searchTerm: '' // 搜索框中的输入
                }
            },
            created() {
                this.fetchCircle();
            },
            methods: {
                handleSearchCircle() {
                    this.fetchCircle();
                },
                async fetchCircle() {
                    try {
                        const response = await fetch(`http://localhost:3000/api/circles?search=${this.searchTerm}`);
                        const result = await response.json();
                        console.log('Circles:', result);
                        this.circles = result;
                    } catch (error) {
                        console.error('获取circles失败：', error);
                    }
                }
            }
        }
        const app4 = Vue.createApp(App4);
        app4.mount('.circle-page')
    </script>

</body>

</html>